<template>
  <div style="border: 1px solid #ccc;" :style="{ '--rich-editor-height': editorHeight }">
    <Toolbar
      style="border-bottom: 1px solid #ccc"
      :editor="editor"
      :default-config="toolbarConfig"
    />
    <Editor
      :default-config="editorConfig"
      @on-created="onCreated"
      @on-destroyed="onDestroyed"
      @on-change="onChange"
      @on-focus="onFocus"
      @on-blur="onBlur"
    />
  </div>
</template>

<script setup>
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import oss from "@/plugins/ossUtil.js"

const props = defineProps({
  content: {
    type: String,
    default: ''
  },
  disabled: {
    type: Boolean,
    default: false
  },
  placeholder: {
    type: String,
    default: '请输入内容...'
  },
  uploadPath: {
    type: String,
    default: ''
  },
  height: {
    type: [String, Number],
    default: '400px'
  },
  isSimple: {
    type: Boolean,
    default: false
  }
})

const emits = defineEmits(['change', 'focus', 'blur'])

const editor = ref(null)
const curValue = ref('')
const imgUrls = ref([])

// 计算属性
const editorHeight = computed(() => {
  return typeof props.height === 'number' ? props.height + 'px' : props.height
})

// 工具栏配置
const toolbarConfig = computed(() => ({
  toolbarKeys: props.isSimple ? [
    'bold', 'through', 'underline', 'sub', 'sup', 'code', 'clearStyle', '|',
    'codeBlock', 'uploadImage', 'undo', 'redo',
  ] : [
    "headerSelect",
    "blockquote",
    "|",
    "bold",
    "underline",
    "italic",
    {
      "key": "group-more-style",
      "title": "更多",
      "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path><path d=\"M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path><path d=\"M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path></svg>",
      "menuKeys": ["through", "code", "sup", "sub", "clearStyle"]
    },
    "color",
    "bgColor",
    "|",
    "fontSize",
    "fontFamily",
    "lineHeight",
    "|",
    "bulletedList",
    "numberedList",
    "todo",
    {
      "key": "group-justify",
      "title": "对齐",
      "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z\"></path></svg>",
      "menuKeys": [
        "justifyLeft",
        "justifyRight",
        "justifyCenter",
        "justifyJustify"
      ]
    },
    {
      "key": "group-indent",
      "title": "缩进",
      "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z\"></path></svg>",
      "menuKeys": [
        "indent",
        "delIndent"
      ]
    },
    "|",
    "emotion",
    "insertLink",
    {
      "key": "group-image",
      "title": "图片",
      "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z\"></path></svg>",
      "menuKeys": [
        "insertImage",
        "uploadImage"
      ]
    },
    {
      "key": "group-video",
      "title": "视频",
      "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M981.184 160.096C837.568 139.456 678.848 128 512 128S186.432 139.456 42.816 160.096C15.296 267.808 0 386.848 0 512s15.264 244.16 42.816 351.904C186.464 884.544 345.152 896 512 896s325.568-11.456 469.184-32.096C1008.704 756.192 1024 637.152 1024 512s-15.264-244.16-42.816-351.904zM384 704V320l320 192-320 192z\"></path></svg>",
      "menuKeys": [
        "insertVideo",
        "uploadVideo"
      ]
    },
    "codeBlock",
    "divider",
    "|",
    "undo",
    "redo",
    "fullScreen"
  ]
}))

// 编辑器配置
const editorConfig = computed(() => ({
  placeholder: props.placeholder,
  readOnly: props.disabled,
  MENU_CONF: {
    uploadImage: {
      async customUpload(file, insertFn) {
        const retUrl = await oss.upload(file, props.uploadPath)
        if (retUrl) {
          imgUrls.value.push(retUrl)
          insertFn(retUrl, '图片', '')
        }
      }
    }
  }
}))

// 监听属性变化
watch(() => props.content, (newVal) => {
  if (editor.value && curValue.value !== newVal) {
    curValue.value = newVal
    if (newVal) {
      editor.value.setHtml(newVal)
    } else {
      editor.value.clear()
    }
  }
})

watch(() => props.disabled, (newVal) => {
  if (!editor.value) return
  if (newVal) {
    editor.value.disable()
  } else {
    editor.value.enable()
  }
})

// 方法
const onChange = (editorInstance) => {
  curValue.value = editorInstance.isEmpty() ? '' : editorInstance.getHtml()
  emits('change', curValue.value)
}

const onCreated = (editorInstance) => {
  editor.value = Object.seal(editorInstance)
  editor.value.setHtml(props.content)
  if (props.disabled) {
    editorInstance.disable()
  }
}

const onDestroyed = (editorInstance) => {
  editorInstance.destroy()
  editor.value = null
}

const onFocus = () => emits('focus')
const onBlur = () => emits('blur')

// 清理已上传但已删除的图片
const clearImg = () => {
  const useImgs = editor.value.getElemsByType('image')?.map(item => item.src) || []
  const a = new Set(useImgs)
  const b = new Set([...imgUrls.value, ...useImgs])
  const removeImgs = Array.from(
      new Set(
          [...b].filter(x => !a.has(x))
      )
  )

  if (removeImgs.length > 0) {
    oss.deleteMulti(removeImgs)
  }
  return useImgs
}

// 暴露方法供外部使用
defineExpose({
  clearImg
})
</script>

<style scoped lang="scss">
:deep(.w-e-text-container) {
  height: var(--rich-editor-height) !important;
}
</style>
